package com.sxz.mall.mallcart.service.impl;

import com.alibaba.fastjson.JSON;
import com.sxz.mall.common.constant.CartConstant;
import com.sxz.mall.common.utils.R;
import com.sxz.mall.common.vo.MemberVO;
import com.sxz.mall.mallcart.feign.ProductFeignService;
import com.sxz.mall.mallcart.interceptor.AuthInterceptor;
import com.sxz.mall.mallcart.service.ICartService;
import com.sxz.mall.mallcart.vo.Cart;
import com.sxz.mall.mallcart.vo.CartItem;
import com.sxz.mall.mallcart.vo.SkuInfoVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

/**
 * 购物车信息存储在redis
 */
@Service
public class CartServiceImpl implements ICartService {

    @Autowired
    StringRedisTemplate redisTemplate;

    @Autowired
    ProductFeignService productFeignService;

    @Autowired
    ThreadPoolExecutor poolExecutor;

    @Override
    public Cart getCartList() {
        BoundHashOperations<String, Object, Object> map = extracted();
        Set<Object> keys = map.keys();
        Cart cart = new Cart();
        List<CartItem> list = new ArrayList<>();
        for (Object key : keys) {
            CartItem cartItem = JSON.parseObject
                    ((String) map.get((String) key), CartItem.class);
            list.add(cartItem);
        }
        cart.setItems(list);
        return cart;
    }


    /**
     * 添加购物车具体逻辑
     *
     * @param skuId
     * @param num
     * @return
     */
    @Override
    public CartItem addCart(Long skuId, Integer num) throws ExecutionException, InterruptedException {

        // 获取到该用户存储在redis中的hashMap数据
        BoundHashOperations<String, Object, Object> boundHashOps = extracted();

        // jsonstring格式==obj
        Object object = boundHashOps.get(skuId.toString());
        if (object != null) {
            String o = (String) object;
            CartItem item = JSON.parseObject(o, CartItem.class);
            item.setCount(item.getCount() + num);
            boundHashOps.put(skuId.toString(), JSON.toJSONString(item));
            return item;
        }
        CartItem cartItem = new CartItem();
        // 异步编排
        CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> {

            // 远程获取商品信息,
            R r = productFeignService.info(skuId);
//        System.out.println("根据skuId获取到的商品信息"+);
//            SkuInfoVo skuInfo = r.get("skuInfoJSON");
            SkuInfoVo skuInfo = JSON.parseObject((String) r.get("skuInfoJSON"), SkuInfoVo.class);

            cartItem.setCheck(true);
            cartItem.setCount(num);
            cartItem.setPrice(skuInfo.getPrice());
            cartItem.setSkuId(skuId);
            cartItem.setTitle(skuInfo.getSkuTitle());
            cartItem.setSpuId(skuInfo.getSpuId());
        }, poolExecutor);

        CompletableFuture<Void> future2 = CompletableFuture.runAsync(() -> {
            // 远程获取销售属性
            List<String> skuSaleAttrs = productFeignService.getSkuSaleAttrs(skuId);
            cartItem.setSkuAttr(skuSaleAttrs);
        }, poolExecutor);

        // 阻塞等待结果
        CompletableFuture.allOf(future1, future2).get();


        // 存储数据到redis中
        String s = JSON.toJSONString(cartItem);
        boundHashOps.put(skuId.toString(), s);

        return cartItem;
    }

    @Override
    public List<CartItem> getUserCartItems() {
        BoundHashOperations<String, Object, Object> hashOperations = extracted();
        List<CartItem> list = hashOperations.values().stream().map((item) -> {
            CartItem cartItem = JSON.parseObject((String) item, CartItem.class);
            return cartItem;
        }).collect(Collectors.toList());

        return list;
    }

    /**
     * 从redis缓存中获取对应用户的购物车列表数据
     * @return
     */
    private BoundHashOperations<String, Object, Object> extracted() {
        MemberVO memberVO = AuthInterceptor.threadLocal.get();
        String cartKey = CartConstant.CART_PERFIX + memberVO.getId();
        return redisTemplate.boundHashOps(cartKey);
    }
}
